package com.wmjsoft.plugins.nutzplugin.dao

import org.nutz.dao.Cnd
import org.nutz.dao.QueryResult
import org.nutz.dao.Sqls
import org.nutz.dao.sql.Criteria
import org.nutz.dao.util.cri.SqlExpressionGroup

/**
 * 如果我没有写注释，请提醒我
 * @program: Maternal
 * @description:
 * @author: Mr.Lee
 * @create: 2021-02-20 14:58
 */
class Wherer(private var queerSql: QueerSql) {


    fun delete(): Int {
        return this.queerSql.delete()
    }

    fun update(): Int {
        return this.queerSql.update()
    }

    fun <DTO> list(dtoClazz: Class<DTO>?): List<DTO>? {
        return this.queerSql.listExecute(dtoClazz!!)
    }

    fun <DTO> one(dtoClazz: Class<DTO>): DTO? {
        return this.queerSql.oneExecute(dtoClazz)
    }

    fun <DTO> page(dtoClazz: Class<DTO>, pageNumber: Int, pageSize: Int): QueryResult? {
        return Pager(this.queerSql).result(dtoClazz, pageNumber, pageSize)
    }

    fun count(clazz:Class<*>): Int {
        return this.queerSql.selectCount(clazz)
    }


    /**
     *
     * @param field 关联字段
     * @param sql select id from 关联表 where name = '%s'
     * @param value 变量
     * @return
     */
    fun inBySql(field: String?, sql: String?, vararg value: Any?): Wherer {
        this.queerSql.cnd!!.where().andInBySql(field, sql, value)
        return this
    }


    fun by(filed: String?, op: String?, value: String?): Wherer {
        if (value == null) {
            return this
        }
        this.queerSql.cnd!!.where().and(filed, op, value)
        return this
    }

    fun eq(filed: String, value: Any?, vararg clazzs: Class<*>): Wherer {
        this.queerSql.cnd!!.where().andEX(queerSql.addTableName(filed, *clazzs), "=", value)
        return this
    }

    fun notEq(filed: String, value: Any?, vararg clazzs: Class<*>?): Wherer {
        this.queerSql.cnd!!.where().andEX(queerSql.addTableName(filed, *clazzs), "!=", value)
        return this
    }

    fun isNull(filed: String, vararg clazzs: Class<*>?): Wherer {
        this.queerSql.cnd!!.where().andIsNull(queerSql.addTableName(filed, *clazzs))
        return this
    }

    fun isNotNull(filed: String, vararg clazzs: Class<*>?): Wherer {
        this.queerSql.cnd!!.where().andNotIsNull(queerSql.addTableName(filed, *clazzs))
        return this
    }


    fun like(filed: String, value: String?, vararg clazzs: Class<*>?): Wherer {
        this.queerSql.cnd!!.where().andEX(queerSql.addTableName(filed, *clazzs), "like", value)
        return this
    }

    fun ge(filed: String, value: Any?, vararg clazzs: Class<*>?): Wherer {
        this.queerSql.cnd!!.where().andEX(queerSql.addTableName(filed, *clazzs), ">=", value)
        return this
    }

    fun gt(filed: String, value: Any?, vararg clazzs: Class<*>?): Wherer {
        this.queerSql.cnd!!.where().andEX(queerSql.addTableName(filed, *clazzs), ">", value)
        return this
    }

    fun le(filed: String, value: Any?, vararg clazzs: Class<*>?): Wherer {
        this.queerSql.cnd!!.where().andEX(queerSql.addTableName(filed, *clazzs), "<=", value)
        return this
    }

    fun lt(filed: String, value: Any?, vararg clazzs: Class<*>?): Wherer {
        this.queerSql.cnd!!.where().andEX(queerSql.addTableName(filed, *clazzs), "<", value)
        return this
    }

    fun `in`(filed: String, list: List<*>?, vararg clazzs: Class<*>?): Wherer {
        this.queerSql.cnd!!.where().andEX(queerSql.addTableName(filed, *clazzs), "in", list)
        return this
    }

    fun notIn(filed: String, list: List<*>?, vararg clazzs: Class<*>?): Wherer {
        this.queerSql.cnd!!.where().andEX(queerSql.addTableName(filed, *clazzs), "not in", list)
        return this
    }

    fun andOr(vararg eres: Ere): Wherer {
        val c = getSqlExpressionGroup(*eres)
        this.queerSql.cnd!!.where().and(c)
        return this
    }



    fun orOr(vararg eres: Ere): Wherer {
        val c = getSqlExpressionGroup(*eres)
        this.queerSql.cnd!!.where().or(c)
        return this
    }

    fun orderBy(filed: String, dir: String?, vararg clazz: Class<*>?): Wherer {
        this.queerSql.cnd!!.orderBy.orderBy(queerSql.addTableName(filed, *clazz), dir)
        return this
    }


    fun max(filed: String, vararg clazz: Class<*>?): Wherer {
        this.queerSql.cnd!!.orderBy.orderBy("MAX( ${queerSql.addTableName(filed, *clazz)}  )", "desc")
        this.queerSql.cnd!!.groupBy.groupBy(this.queerSql.addTableName(filed, *clazz))
        return this
    }

    fun min(filed: String, vararg clazz: Class<*>?): Wherer {
        this.queerSql.cnd!!.orderBy.orderBy("MIN(" + queerSql.addTableName(filed, *clazz)+ ")", "asc")
        this.queerSql.cnd!!.groupBy.groupBy(this.queerSql.addTableName(filed, *clazz))
        return this
    }


    fun groupBy(names: String,vararg clazz: Class<*>): Wherer {
        val strs = names.split(",").toTypedArray()
        val sb = StringBuilder()
        for (str in strs) {
            if(clazz.isEmpty()){
                sb.append(this.queerSql.getTableName(this.queerSql.clazz) + "." + str + ",")
            }else{
                sb.append(this.queerSql.getTableName(clazz[0]) + "." + str + ",")
            }
        }
        sb.deleteCharAt(sb.lastIndexOf(","))
        this.queerSql.cnd!!.groupBy.groupBy(sb.toString())
        return this
    }




    private fun getSqlExpressionGroup(vararg eres: Ere): SqlExpressionGroup? {
        var c: SqlExpressionGroup? = null
        for (e in eres) {
            val str: List<String> = e.filed!!.split("\\.")
            if ("$" == str[0]) {
                e.filed = this.queerSql.getTableName(this.queerSql.clazz) + "." + str[1]
            }
            if (null == c) {
                c = Cnd.exps(e.filed, e.op, e.value)
            } else {
                c.or(Cnd.exps(e.filed, e.op, e.value))
            }
        }
        return c
    }
}